package cloud.hedou.abp.post

import cloud.hedou.abp.remote.HttpClient
import cloud.hedou.abp.remote.PagedList
import cloud.hedou.abp.webcore.ForbiddenException
import com.nimbusds.jose.util.JSONObjectUtils
import org.springframework.retry.annotation.Backoff
import org.springframework.retry.annotation.Retryable
import org.springframework.scheduling.annotation.Async
import org.springframework.stereotype.Service
import retrofit2.HttpException

@Service
class RemotePostService(
    httpClient: HttpClient,
) {

    private val postApi = httpClient.create(PostApi::class.java)

    @Async
    @Retryable(
        maxAttempts = 100,
        backoff = Backoff(delay = 1000 * 60)
    )
    fun registerBusiness(vararg businesses: PostBusinessPayload) {
        val call = postApi.createBusiness(
            PagedList(
                totalCount = businesses.size,
                items = businesses.toList()
            )
        )
        val response = call.execute()
        if (!response.isSuccessful) {
            throw HttpException(response)
        }
    }

    fun checkOrThrows(
        businessName: String,
        userId: String,
        departmentId: String? = null,
        includeChildren: Boolean = false,
    ) {
        val call = postApi.check(
            PostCheckPayload(
                businessName = businessName,
                userId = userId,
                departmentId = departmentId,
                includeChildren = includeChildren
            )
        )
        val response = call.execute()
        if (!response.isSuccessful) {
            val jsonObject = JSONObjectUtils.parse(response.errorBody()?.string())
            val error = JSONObjectUtils.getJSONObject(jsonObject, "error")
            val message = JSONObjectUtils.getString(error, "message")
            throw ForbiddenException(message, HttpException(response))
        }
    }

    fun getGrantedDepartmentIds(
        businessName: String,
        departmentIds: List<String>,
        includeChildren: Boolean? = null,
    ): List<String> {
        val call = postApi.getGrantedDepartmentIds(
            GetGrantedDepartmentIdsPayload(
                businessName = businessName,
                departmentIds = departmentIds,
                includeChildren = includeChildren,
            )
        )
        val response = call.execute()
        if (!response.isSuccessful) {
            val jsonObject = JSONObjectUtils.parse(response.errorBody()?.string())
            val error = JSONObjectUtils.getJSONObject(jsonObject, "error")
            val message = JSONObjectUtils.getString(error, "message")
            throw ForbiddenException(message, HttpException(response))
        }
        return response.body() ?: emptyList()
    }

    fun hasPermission(
        businessName: String,
        userId: String,
        departmentId: String? = null,
        includeChildren: Boolean? = null,
    ): Boolean {
        val call = postApi.hasPermission(
            PostCheckPayload(
                businessName = businessName,
                userId = userId,
                departmentId = departmentId,
                includeChildren = includeChildren
            )
        )
        val response = call.execute()
        if (!response.isSuccessful) {
            throw HttpException(response)
        }
        return response.body() == true
    }

}